home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 17
/
CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso
/
CUCD
/
Programming
/
DiceSource
/
src
/
dcpp
/
precomp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-09-09
|
9KB
|
441 lines
/*
* (c)Copyright 1992-1997 Obvious Implementations Corp. Redistribution and
* use is allowed under the terms of the DICE-LICENSE FILE,
* DICE-LICENSE.TXT.
*/
/*
* PRECOMP.C
*
* handle precompiled includes
*
*/
#include "defs.h"
#ifdef AMIGA
#include "/dc1/tokens.h"
#else
#include "../dc1/tokens.h"
#endif
#define THASHSIZE 256
#define THASHMASK (THASHSIZE-1)
#define FASTPRECOMP 1
Prototype void InitPrecomp(void);
Prototype void LoadPrecompiledHeader(char *, PreCompHdr *, int);
Prototype short PreCompSymbol(char *, short);
/*Prototype void DumpPrecompiledHeader(PreCompNode *, FILE *, long, long);*/
Prototype void DumpPrecompiledPrefix(PreCompNode *);
Prototype void DumpPrecompiledPostfix(PreCompNode *, FILE *);
typedef struct TokenNode {
struct TokenNode *tn_Next;
char *tn_Name;
short tn_Len;
short tn_Token;
} TokenNode;
#define MakeToken(name,token) { NULL, name, sizeof(name) - 1, (((token >> 4) & 0xFF00) | (ubyte)token | TOKF_PRIVATE) }
TokenNode TokenAry[] = {
MakeToken("sizeof", TokSizeof),
MakeToken("break", TokBreak),
MakeToken("case", TokCase),
MakeToken("continue", TokContinue),
MakeToken("default", TokDefault),
MakeToken("do", TokDo),
MakeToken("else", TokElse),
MakeToken("for", TokFor),
MakeToken("goto", TokGoto),
MakeToken("if", TokIf),
MakeToken("return", TokReturn),
MakeToken("struct", TokStruct),
MakeToken("enum", TokEnum),
MakeToken("switch", TokSwitch),
MakeToken("union", TokUnion),
MakeToken("while", TokWhile),
MakeToken("typedef", TokTypeDef)
};
TokenNode *TokenHash[THASHSIZE];
/*char CharType[256];*/
void
InitPrecomp()
{
TokenNode *tn;
TokenNode **tp;
for (tn = TokenAry; tn < &TokenAry[arysize(TokenAry)]; ++tn) {
tp = &TokenHash[hash(tn->tn_Name, tn->tn_Len) & THASHMASK];
tn->tn_Next = *tp;
*tp = tn;
}
}
short
PreCompSymbol(char *ptr, short len)
{
TokenNode *tn;
for (tn = TokenHash[hash(ptr, len) & THASHMASK]; tn; tn = tn->tn_Next) {
/*fprintf(stderr, "%d %d %.*s %.*s\n", len, tn->tn_Len, len, ptr, tn->tn_Len, tn->tn_Name);*/
if (len == tn->tn_Len && cmpmem(tn->tn_Name, ptr, len) == 0) {
return(tn->tn_Token);
}
}
return(0);
}
/*
* Load precompiled header from file descriptor / specified device.
* copy preprocessed data directly to Fo and incorporate symbol table
* additions.
*/
void
LoadPrecompiledHeader(fileName, pch, fd)
char *fileName;
PreCompHdr *pch;
int fd;
{
/*
* copy preprocessor dump
*/
if (pch->pc_CppSize) {
long bufsiz = ((pch->pc_CppSize > 32768) ? 32768 : pch->pc_CppSize);
char *buf;
#if !FASTPRECOMP
long bytes = pch->pc_CppSize;
#endif
if ((buf = malloc(bufsiz)) == NULL)
ErrorNoMemory();
#if FASTPRECOMP
fprintf(Fo, "#precomp %ld %ld \"%s\"\n", (long)lseek(fd, 0, 1), pch->pc_CppSize, fileName);
lseek(fd, pch->pc_CppSize, 1);
#else
xxx;
bytes -= 4; /* don't embed \0's */
while (bytes) {
long n;
n = read(fd, buf, ((bytes > bufsiz) ? bufsiz : bytes));
if (n < 0)
cerror(EFATAL_READ_PRECOMP);
fwrite(buf, n, 1, Fo);
bytes -= n;
}
free(buf);
#endif
}
/*
* incorporate symbol set pc_SymSize
*
* scan symbols in reverse
*/
if (pch->pc_SymSize) {
char *symData;
long i;
long j;
if ((symData = malloc(pch->pc_SymSize)) == NULL)
ErrorNoMemory();
if (read(fd, symData, pch->pc_SymSize) != pch->pc_SymSize)
cerror(EFATAL_PARSE_PRECOMP);
for (i = pch->pc_SymSize - 4; i > 0; i = j - 8) {
j = i - *(long *)(symData + i);
DefinePrecompSymbol((Sym *)(symData + j));
}
}
}
/*
* Dump prefix and postfix for preprocessed headers
*/
void
DumpPrecompiledPrefix(pcn)
PreCompNode *pcn;
{
PreCompHdr pch;
/*
* dummy header
*/
pch.pc_Magic = 0; /* bad value for now */
pch.pc_SymSize = 0;
pch.pc_CppSize = 0;
pch.pc_Version[0] = 0;
fwrite(&pch, 1, sizeof(pch), Fo);
fputc('\n', Fo); /* need an initial newline */
}
/*
* Dump Postfix for precompiled headers
*
* Note that foOrig is our cpp output file, NOT the precompiled output
* file (which is still Fo)
*/
void
DumpPrecompiledPostfix(pcn, foOrig)
PreCompNode *pcn;
FILE *foOrig;
{
PreCompHdr pch;
long pos1;
long pos2;
fwrite("\0\0\0\0", 4, 1, Fo); /* terminator for DC1 */
pos1 = ftell(Fo);
DumpPrecompSymbols(Fo);
pos2 = ftell(Fo);
/*
* fixup header
*/
fseek(Fo, 0L, 0);
pch.pc_Magic = PCH_MAGIC;
pch.pc_SymSize = pos2 - pos1;
pch.pc_CppSize = pos1 - sizeof(pch);
strcpy(pch.pc_Version, VersionId);
fwrite(&pch, sizeof(pch), 1, Fo);
#if FASTPRECOMP
fprintf(foOrig, "#precomp %d %ld \"%s\"\n",
sizeof(pch),
pch.pc_CppSize,
pcn->pn_OutName
);
#else
{
static char XBuf[2048];
long n;
long s;
for (s = pch.pc_CppSize; s; s -= n) {
n = (s < sizeof(XBuf)) ? s : sizeof(XBuf);
if (fread(XBuf, 1, n, Fo) == n) {
if (fwrite(XBuf, 1, n, foOrig) != n) {
exit(22);
}
} else {
exit(22);
}
}
}
#endif
}
/*
* Save preprocessed header from fo<begpos-endpos> to pcn->pn_OutName,
* also save symbol table
*/
#ifdef NOTDEF3
void
DumpPrecompiledHeader(pcn, fi, begpos, endpos)
PreCompNode *pcn;
FILE *fi;
long begpos;
long endpos;
{
PreCompHdr pch;
FILE *fo;
long pos;
static char *SymRefPtr[256];
static long SymRefLen[256];
#ifdef NOTDEF
short symRefIdx = 0;
#endif
setmem(SymRefLen, sizeof(SymRefLen), 0);
if ((fo = fopen(pcn->pn_OutName, "w+")) == NULL)
cerror(EFATAL_CANT_CREATE_FILE, pcn->pn_OutName);
if (fseek(fi, begpos, 0) < 0)
cerror(EFATAL_SEEK_PRECOMP);
/*
* dummy header
*/
pch.pc_Magic = 0; /* bad value for now */
pch.pc_SymSize = 0;
pch.pc_CppSize = 0;
pch.pc_Version[0] = 0;
fwrite(&pch, 1, sizeof(pch), fo);
/*
* copy preprocessor dump to precomp file, tokenize simple constructs
*/
if (endpos != begpos) {
char *buf;
long bytes = endpos - begpos;
long j = 0;
short c;
short wsFlag = 0; /* remove white space flag */
if ((buf = malloc(bytes)) == NULL)
ErrorNoMemory();
if (fread(buf, bytes, 1, fi) != 1)
cerror(EFATAL_READ_PRECOMP);
pch.pc_CppSize = bytes;
fwrite(buf, bytes, 1, fo);
#ifdef NOTDEF2 /* doesn't help enough */
while (j < bytes) {
long i;
c = buf[j];
/*
* Scan for symbols. Ignore symbols that are part of numbers
* because DC1 cannot parse that. We must also ignore
* quoted strings and character constants.
*/
switch(CharType[c]) {
case -2: /* white space */
if (wsFlag) {
--pch.pc_CppSize;
} else {
putc(c, fo);
wsFlag = 1;
}
++j;
continue;
case -1: /* quote or single quote */
wsFlag = 0;
for (i = j, ++j; j < bytes && buf[j] != buf[i]; ++j) {
if (buf[j] == '\\')
++j;
}
++j;
fwrite(buf + i, j - i, 1, fo);
break;
case 0: /* not anything remarkable */
wsFlag = 0;
putc(c, fo);
++j;
break;
case 3:
for (i = j, ++j; j < bytes && buf[j] != '\n'; ++j)
;
fwrite(buf + i, j - i, 1, fo);
break;
case 1: /* number */
/*
* In parsing a number we skip potential symbols embedded
* in the number because DC1 cannot handle this case.
*/
wsFlag = 0;
for (i = j, ++j; j < bytes && (CharType[c = buf[j]] > 0 || c == '.'); ++j)
;
fwrite(buf + i, j - i, 1, fo);
break;
case 2: /* symbol */
/*
* In parsing a symbol note that numerical types are valid
* symbol characters after the first character, e.g. A23
*/
wsFlag = 0;
{
TokenNode *tn;
char *ptr = buf + j;
for (i = j, ++j; j < bytes && CharType[buf[j]] > 0; ++j)
;
i = j - i; /* i == length of symbol */
for (tn = TokenHash[hash(ptr, i) & THASHMASK]; tn; tn = tn->tn_Next) {
if (tn->tn_Len == i && cmpmem(ptr, tn->tn_Name, i) == 0)
break;
}
if (tn) {
fwrite(&tn->tn_Token, sizeof(tn->tn_Token), 1, fo);
pch.pc_CppSize -= i - sizeof(tn->tn_Token);
wsFlag = 1;
} else {
#ifdef NOTDEF
short idx;
/*
* check previously used symbols. When placing
* a reference use a simple 8 bit hash value but
* leave room to allow DC1 to change it to a
* real pointer.
*/
for (idx = (symRefIdx - 1) & 255; idx != symRefIdx; idx = (idx - 1) & 255) {
if (i == SymRefLen[idx] && cmpmem(SymRefPtr[idx], ptr, i) == 0)
break;
}
idx = (symRefIdx - idx) & 255;
if (idx > 0 && idx < 128) {
putc(TokCppRef1_Byte, fo);
putc(idx, fo);
pch.pc_CppSize -= i - sizeof(tn->tn_Token);
wsFlag = 1;
} else
#endif
{
#ifdef NOTDEF
SymRefPtr[symRefIdx] = ptr;
SymRefLen[symRefIdx] = i;
symRefIdx = (symRefIdx + 1) & 0xFF;
#endif
fwrite(ptr, i, 1, fo);
wsFlag = 0;
}
}
}
break;
}
}
#endif
free(buf);
}
fseek(fo, 0L, 1);
pos = ftell(fo);
/*
* dump symbols
*/
DumpPrecompSymbols(fo);
/*
* fixup header
*/
pch.pc_Magic = PCH_MAGIC;
pch.pc_SymSize = ftell(fo) - pos;
strcpy(pch.pc_Version, VersionId);
fseek(fo, 0L, 0);
fwrite(&pch, sizeof(pch), 1, fo);
fclose(fo);
fseek(fi, endpos, 0);
}
#endif